#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/input.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <stdbool.h>

static bool isRunning = false;

void *thread_callback(void *args)
{
    int ret;
    int fd = *(int*)args;
    int epollfd = epoll_create(1);
    struct epoll_event e;
    struct input_event input;
    e.events = EPOLLIN | EPOLLET;
    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &e) == -1) {
        printf("[%s][%d]epoll add filefd failed. %s\n", __func__, __LINE__, strerror(errno));
        return NULL;
    }
    while (isRunning) {
        ret = epoll_wait(epollfd, &e, 2, 1000); // timeout(ms)
        if (ret < 0) {
            printf("[%s][%d]epoll_wait error. %s\n", __func__, __LINE__, strerror(errno));
        } else if (ret > 0) {
            if (e.events != EPOLLIN) {
                printf("[%s][%d] isn't a read event\n", __func__, __LINE__);
                continue;
            }
            if (read(fd, &input, sizeof(input))) {
                switch (input.type) {
                    case EV_KEY:
                        switch (input.code) {
                            case KEY_0:
                                printf("[%s][%d]key pressed, value=%d\n", __func__, __LINE__, input.value);
                                break;
                            default:
                                printf("[%s][%d]unkwon key code:%u\n", __func__, __LINE__, input.code);
                        }
                        break;                   
                }
            } else {
                printf("[%s][%d]read input event error. %s\n", __func__, __LINE__, strerror(errno));
            }
        }
    }

    close(epollfd);
    return NULL;
}

int main(int argc, char *argv[])
{
    char cmd[20];
    pthread_t thread;
    pthread_attr_t attr;
    char *filename = argv[1];
    int fd = open(filename, O_RDWR | O_NONBLOCK, S_IRWXU);
    if (fd <= 0) {
        printf("[%s][%d]open file %s failed. %s\n", __func__, __LINE__, filename, strerror(errno));
        return -1;
    }

    isRunning = true;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if (pthread_create(&thread, &attr, thread_callback, &fd)) {
        printf("[%s][%d]create thread failed\n", __func__, __LINE__);
        return -1;
    }
    pthread_setname_np(thread, "rk3588-gpio-input-epoll-thread");
    pthread_attr_destroy(&attr);

    while (1) {
        printf("cmd:");
        memset(cmd, 0, 20);
        scanf("%s", cmd);
        if (!strcmp(cmd, "quit") || !strcmp(cmd, "q")) {
            printf("quit\n");
            break;
        } else {
            printf("unkwon cmd\n");
        }                
    }

    isRunning = false;
    close(fd);
    return 0;
}